基于openGL中shader聊滤镜特效的原理和实际应用 |
您所在的位置:网站首页 › shader 算法 › 基于openGL中shader聊滤镜特效的原理和实际应用 |
目标
最终能够自己通过OpenGL或者借助一些三方库GPUImage写一些简单的滤镜、特效shader,明白原理和整个流程 OpenGL简介OpenGL是各个平台的统称,移动端的是OpenGL ES,web端的是WebGL (备注:下文将OpenGL ES将简称OpenGL) 为什么用OpenGL 定义了一套平台无关的图形操作API,提供了访问GPU的能力。 为CPU和GPU的数据交换定义了缓存(buffer),因为从一个内存区域复制到另一个内存区域的速度是相对较慢的,并且在内存复制的过程中,CPU 和 GPU 都不能处理这区域内存下图是一个移动设备图像渲染框架草图: 在进入主题之前,我们再来了解下图片渲染到屏幕的过程,这将有助于了解OpenGL在滤镜特效中的作用 正是因为有了OpenGL的存在,我们才可以对图像、视频做很多有意思的处理,而这一部分离不开OpenGL中的着色器——Shader,下面就来看看 什么是ShaderOpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转变为适应你屏幕的2D像素。 3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线管理的,图形渲染管线可以被划分为几个阶段,每个阶段将会把前一个阶段的输出作为输入 下面来看看OpenGL世界中的"Hello world"(三角形)怎么实现. 这里主要说下顶点着色器和片段着色器 顶点着色器如果需要对图像进行缩放变化,比如放大,缩小,移动效果,则需要对顶点着色器重新编程,默认顶点着色器代码如下 attribute vec4 Position; // 顶点坐标 attribute vec2 TextureCoords; // 纹理坐标 varying vec2 TextureCoordsVarying;//片段着色器的输入(纹理坐标) void main (void) { gl_Position = Position; TextureCoordsVarying = TextureCoords; } 复制代码 片段着色器如果需要对原始图像最终输出的颜色进行调整,则需要对片段着色器重新编程 precision mediump float; uniform sampler2D Texture;//纹理采样器 varying vec2 TextureCoordsVarying; //顶点着色器传过来的纹理坐标 void main (void) { //图元的每个顶点各自对应纹理坐标,用来标明该从纹理图像的哪个部分采样 vec4 mask = texture2D(Texture, TextureCoordsVarying);//获得纹理坐标相应位置的颜色 gl_FragColor = vec4(mask.rgb, 1.0); } 复制代码用顶点着色器和片段着色器可以写出各种各种样的opengl程序 OpenGL中坐标系(可选)了解OpenGL中的坐标系,有助于更好的了解openGL渲染管线和作业的流程: 友情链接:OpenGL ES顶点坐标 纹理坐标 有了上面shader的铺垫,那可以思考下滤镜和特效怎么实现的了? 滤镜的原理和实现颜色滤镜一般不需要用到顶点着色器 什么是滤镜在 app 内利用各种图形算法可以对图片进行一些变换,这样的效果也称为“滤镜”,滤镜效果大致可以分为以下几类: 独立像素点变换:包括亮度、对比、饱和度、色调、灰色化、分离RGB通道等 像素卷积变换:包括边缘检测、浮雕化、模糊、锐化(比如美颜) 仿射矩阵变换: 包括缩放、旋转、倾斜、扭曲、液化等() 多图像合成 其中最简单的就是进行独立像素点变换,最简单的滤镜就是第1点:独立像素点变换,也可以叫做颜色滤镜,最主要的技术就是ColorLUT ColorLUT下图是一个标准的颜色查找表 在一张表中为每种颜色(总共255 * 255 * 255)记录一个对应的映射目标颜色。当用【颜色查找表】对一张照片做颜色映射时,只需要遍历照片的每个像素点,然后在表中找到该像素颜色对应的目标颜色,最后将该像素设置为目标颜色即可 比如原始颜色是红色(r:255,g:0,b:0),进行转换后变为绿色(r:0,g:255,b:0),以后所有是红色的地方都会被自动转换为绿色。而颜色查找表就是将所有的颜色进行一次(矩阵)转换,而很多的滤镜功能就是提供了这么一个转换的矩阵,在原始色彩的基础上进行颜色的转换 如何生成颜色查找表左上角第一个像素代表位于(0,0,0)的点,第二个像素代表位于(85,0,0)的点 具体的实现 demo1:来看一个简单的列子,灰度滤镜的实现(不需要使用ColorLUT): 如果是设计师给的颜色查找表.png怎么用, 这里通过GPUImage中的颜色查找滤镜GPUImageLookupFilter(就是用来处理颜色查找表和原图的)来看下这部分着色器处理的代码 伪代码 precision mediump float; varying highp vec2 textureCoordinate; uniform sampler2D inputImageTexture; //原图纹理 uniform sampler2D inputImageTexture2; // lookup texture void main (void) { //图元的每个顶点各自对应纹理坐标,用来标明该从纹理图像的哪个部分采样 lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1); lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2); //真正的颜色在两个颜色之间(按照一定权重进行混合) lowp vec4 newColor = mix(orginColor(原图纹理颜色), LUTColor(颜色查找表), 权重); gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity); } 复制代码特效的原理和实现比如来看一个比较简单的【分屏】 原理其实就是去改变纹理坐标在y轴的偏移位置 // 精度 precision highp float; // 通过uniform传递过来的纹理 uniform sampler2D Texture; // 纹理坐标 varying highp vec2 varyTextureCoord; void main() { vec2 uv = varyTextureCoord.xy; float y; // 0.0~0.5 范围内显示0.25~0.75范围的像素 if (uv.y >= 0.0 && uv.y |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |